const _ = require('lodash');
const moment = require('moment');
const auto = require('async/auto');
const Table = require('./HtmlTable');
const ECharts = require('./ECharts');

const tableWidth = '';
const borderStyle = 'border: 1px solid #000';
const alignCenter = 'text-align: center';

let app, model, spider, between, lte, gte, or, $in;

class SpiderReportData {
  constructor(_app) {
    app = _app;
    model = _app.model;
    spider = _app.spider;
    const Op = _app.Sequelize.Op;
    lte = Op.lte;
    gte = Op.gte;
    or = Op.or;
    between = Op.between;
    $in = Op.in;
  }

  /**
   * 日志的数据
   * @param project_id
   * @param report_id
   * @param index
   * @param date
   * @returns {Promise<any>}
   */
  async get({project_id, report_id, date, index}) {
    const {Project, Report, DetailAnchor, DetailAnchorData, DetailAnchorSchedule, File} = model;
    const {Platform, PlatformType, Type, TypeData} = spider;

    let report;
    const include = [{model: Project}];
    if (!_.isEmpty(index)) {
      // 日报的短文本ID
      report = await Report.findOne({where: {index}, include});
    } else if (report_id > 0) {
      // 日报数字ID
      report = await Report.findOne(
          {where: {id: report_id}, include});
    }
    else if (!_.isEmpty(date) || !_.isEmpty(project_id)) {
      // 根据项目ID和日期查找
      report = await Report.findOne(
          {where: {project_id, created_at: date}, include});
    }

    if (!report)
      throw new Error('无法找到日志');

    report = report.toJSON();

    const now = new Date(report.created_at);

    const yesterday = moment(now).subtract(1, 'day').format('YYYY-MM-DD'),
        start = moment(now).startOf('day').toDate(),
        end = moment(now).endOf('day').toDate();

    const project = report.project;
    delete report.project;

    return new Promise(resolve => {
      auto({
            //直播记录
            async schedules() {
              let schedulesRes = await DetailAnchorSchedule.findAll({
                where: {
                  project_id: project.id, [or]: {
                    start: {[between]: [start, end]},
                    end: {[between]: [start, end]},
                  },
                },
                order: [['end', 'asc']],
                include: [
                  {model: app.model.Platform, as: 'platform'},
                  {
                    model: DetailAnchor,
                    as: 'anchor',
                    include: [
                      {
                        model: DetailAnchorData,
                        as: 'data',
                        limit: 1,
                        order: [['created_at', 'desc']],
                      }],
                  },
                  {
                    model: File,
                    as: 'images',
                    required: false,
                    where: {selected: true},
                  },
                  {model: File, as: 'image', required: false},
                ],
              });
              schedulesRes = _.sortBy(schedulesRes, 'end');
              const schedules = {};
              schedulesRes.forEach(schedule => {
                if (!schedules[schedule.id])
                  schedules[schedule.id] = schedules[schedule.id];
              });
              return schedulesRes.map(s => {
                const j = s.toJSON();
                j.qrcode = j.qrcode ? 1 : '';
                j.start = moment(j.start).format('MM月DD日 HH点mm分');
                j.end = moment(j.end).format('MM月DD日 HH点mm分');
                return j;
              });
              // return Object.values(schedules);
            },
            //当天的直播类型数据
            async platformType() {
              let platformTypeId = [];
              //项目设置里的分类id
              project.options.aggregation.forEach(item => {
                platformTypeId = platformTypeId.concat(item.data);
              });
              //过滤重复id，过滤无效id
              platformTypeId = _.compact(_.uniq(platformTypeId));
              // console.log('categoriesData 1', pcId);

              const data = await PlatformType.findAll({
                where: {id: {[$in]: platformTypeId}},
                include: [{model: Platform}, {model: Type}],
              });
              // console.log('categoriesData 2', data.length);
              //数组转为对象
              const platformType = {}, platforms = {},
                  types = {};
              data.forEach(pt => {
                pt = pt.toJSON();
                platformType[pt.id] = pt;
                platforms[pt.id] = pt.platform_id;
                types[pt.id] = pt.type_id;
              });
              return {platformType, platforms, types};
            },
            current: [
              'platformType', async res => {
                const {platforms, types} = res.platformType;
                return await TypeData.findAll({
                  raw: true,
                  where: {
                    platform_id: {[$in]: Object.values(platforms)},
                    type_id: {[$in]: Object.values(types)},
                    created_at: report.created_at,
                  },
                  attributes: {exclude: ['created_at', 'updated_at']},
                });
              }],
            yesterday: [
              'platformType', async res => {
                const {platforms, types} = res.platformType;
                return await TypeData.findAll({
                  raw: true,
                  where: {
                    platform_id: {[$in]: Object.values(platforms)},
                    type_id: {[$in]: Object.values(types)},
                    created_at: yesterday,
                  },
                  attributes: {exclude: ['created_at', 'updated_at']},
                });
              }],
            platformTypes: [
              'platformType', 'current', 'yesterday', async res => {
                let {current, yesterday, platformType: {platformType, platforms, types}} = res;

                const yesterdayData = {}, todayData = {};
                yesterday.forEach(data => {
                  yesterdayData[data.platform_id + '_' + data.type_id] = data;
                });
                current.forEach(data => {
                  todayData[data.platform_id + '_' + data.type_id] = data;
                });

                /** 今天与昨天的数据计算出趋势 */
                _.each(current, today => {
                  const key = today.platform_id + '_' + today.type_id;
                  let yesterday = yesterdayData[key];
                  // console.log('趋势', today, yesterdayData);
                  if (yesterday) {
                    if (today.num_active > yesterday.num_active)
                      today.trend = '↑';
                    else if (today.num_active < yesterday.num_active)
                      today.trend = '↓';
                    else
                      today.trend = '=';
                  } else {
                    today.trend = '';
                  }
                });

                const platformData = {};
                /** 数据汇总 */
                _.each(project.options.aggregation, item => {
                  const aggregationData = {};
                  item.data.forEach(p_t_id => {
                    const pId = platforms[p_t_id], tId = types[p_t_id];
                    const key = pId + '_' + tId;
                    const today = {
                      platform: platformType[p_t_id].platform.name,
                      category: platformType[p_t_id].type.name,
                      _new: 0,
                      active: 0,
                      open: 0,
                      watch: 0,
                      rank: '',
                      trend: '',
                    };
                    Object.assign(today, todayData[key]);

                    // 汇总到以平台id为key的对象
                    if (!aggregationData[pId]) {
                      aggregationData[pId] = Object.assign(
                          {types: [platformType[p_t_id].type.name]},
                          today);
                    }
                    else {
                      aggregationData[platforms[p_t_id]].types.push(
                          platformType[p_t_id].type.name);
                      aggregationData[platforms[p_t_id]].num_new += today.num_new;
                      aggregationData[platforms[p_t_id]].num_active += today.num_active;
                      aggregationData[platforms[p_t_id]].num_open += today.num_open;
                      aggregationData[platforms[p_t_id]].num_watch += today.num_watch;
                      aggregationData[platforms[p_t_id]].rank += '/' + today.rank;
                      aggregationData[platforms[p_t_id]].trend += '/' + today.trend;
                    }
                  });
                  platformData[item.name] = Object.values(aggregationData);
                });
                return platformData;
              }],
          },
          (err, res) => {
            if (err)
              console.log('report', err);
            if (!res.schedules)
              res.schedules = [];
            if (!res.platformTypes)
              res.platformTypes = {};
            resolve({
              schedules: res.schedules,
              platformTypes: res.platformTypes,
              project,
              report,
            });
          },
      );
    });
  }

  /**
   * 获取日志的活跃主播趋势
   * @param project_id
   * @param start
   * @param end
   * @returns {Promise<{data: *}>}
   */
  async getActiveAnchor({project_id, start, end}) {
    const {PlatformType, Platform, Type, TypeData} = spider;
    const project = await model.Project.findByPk(project_id);

    let pcId = [], platforms = {}, types = {};

    project.options.aggregation.forEach(item => {
      pcId = pcId.concat(item.data);
    });

    pcId = _.compact(_.uniq(pcId));
    console.log({pcId});

    let platformTypes = await PlatformType.findAll(
        {
          where: {id: {[$in]: pcId}},
          include: [{model: Platform}, {model: Type}],
        });
    platformTypes.forEach(pt => {
      platforms[pt.id] = pt.platform_id;
      types[pt.id] = pt.type_id;
    });

    platformTypes = _.keyBy(platformTypes, 'id');

    let originalData = await TypeData.findAll({
      raw: true,
      where: {
        platform_id: {[$in]: Object.values(platforms)},
        type_id: {[$in]: Object.values(types)},
        created_at: {[gte]: start, [lte]: end},
      },
    });
    // console.log('data length', originalData.length);
    const dateGroup = {};
    originalData.forEach(data => {
      const key = data.platform_id + '_' + data.type_id;
      if (!dateGroup[key])
        dateGroup[key] = [];
      dateGroup[key].push(data);
    });

    end = moment(end);
    let aggregationData = {}, platformCategoryData = {}, date = [];

    pcId.forEach(id => {
      if (!platformCategoryData[id])
        platformCategoryData[id] = {};
      const pid = platforms[id], tid = types[id];
      let data = dateGroup[pid + '_' + tid];
      let _start = moment(start);
      while (_start <= end) {
        const date = _start.format('YYYY-MM-DD');
        let active = 0;
        if (!_.isEmpty(data)) {
          let find = _.find(data, {created_at: date});
          if (find) active = find.num_active;
        }
        platformCategoryData[id][date] = active;
        _start.add(1, 'day');
      }
    });

    /** 列出start和end中间的所有日期 */
    let _start = moment(start);
    while (_start <= end) {
      date.push(_start.format('MM月DD日'));
      _start.add(1, 'day');
    }

    _.each(project.options.aggregation, item => {
      let data = aggregationData[item.name] = {};
      item.data.forEach(id => {
        let {platform_id} = platformTypes[id];
        if (data[platform_id])
          data[platform_id].data = Object.values(platformCategoryData[id]).
              map((active, i) =>
                  data[platform_id].data[i] += active,
              );
        else
          data[platform_id] = {
            data: Object.values(platformCategoryData[id]),
            name: platformTypes[id].platform.name,
            type: 'line',
          };
      });
    });
    _.each(aggregationData, (data, key) => {
      aggregationData[key] = Object.values(data);
    });
    return {date, data: aggregationData};
  }

  /**
   * 将日志数据渲染成HTML，用于发送邮件
   * @param report_id
   * @param appendContent
   * @param {Boolean} isCreateECharts 是否创建ECharts图片文件
   * @returns {Promise<{subject: string, html: string}>}
   */
  async renderHtml(report_id, appendContent, isCreateECharts = true) {
    const {project, report, schedules, platformTypes} = await this.get(
        {report_id});

    let allPlatform = '';
    {
      const header = [
        '排名',
        '平台',
        '*活跃主播',
        '新增主播',
        '开播数',
        '观看人气',
        '昨日对比'];
      _.each(platformTypes, (type, name) => {
        const table = new Table(report.created_at + ' ' + name + ' 数据');
        table.header(header, project.options.color);
        table.sumStartAt(2);
        table.sumSkip(7);
        table._rows = type.map(data =>
            [
              data.rank,
              data.platform,
              data.num_active,
              data.num_new,
              data.num_open,
              data.num_watch,
              data.trend],
        );
        allPlatform += table + '<br>';
      });
    }

    /**活跃主播趋势 区块*/
    let activeAnchorTable = '';
    {
      const start = moment(report.created_at).subtract(6, 'days');
      let {date, data} = await this.getActiveAnchor({
        project_id: project.id,
        start: start.format('YYYY-MM-DD'),
        end: report.created_at,
      });
      let header = ['平台'].concat(date);
      let index = 0;
      _.each(data, (data, category) => {
        //表格部分
        let table = new Table(category + ' 各平台活跃主播统计数据');
        table.header(header, project.options.color);
        table._rows = Object.values(data).map(item => {
          return [item.name].concat(item.data);
        });
        activeAnchorTable += table.toString() + '<br/>';

        //图表部分
        data.forEach(data => {
          data.label = {normal: {show: true}};
        });

        let option = {
          backgroundColor: '#fff',
          title: {text: `${category} 各平台活跃主播变化趋势`},
          grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true,
          },
          legend: {data: _.map(data, 'name'), right: '0%', top: '5%'},
          xAxis: {data: date},
          yAxis: {},
          series: data,
        };

        let file = report_id + '_' + index;

        //创建ECharts的图表图片文件
        if (isCreateECharts) {
          ECharts({
            option,
            path: app.config.screenshot.path,
            file,
          });

          //插入邮件图表到数据库，并设为已使用
          app.model.File.upsert({file, selected: true}).then(() => {
            return app.model.File.findOne({where: {file}});
          }).then(file => {
            app.model.ReportImage.upsert(
                {file_id: file.id, report_id: report.id});
          });
        }

        activeAnchorTable += `<img src="https://live.beijingzhuyou.com/pic/${file}" />`;
        index++;
      });
    }

    /**主播数据*/
    const scheduleTable = new Table(report.created_at + ' 直播反馈信息');
    {
      const platformData = _.groupBy(schedules, 'platform_id');
      scheduleTable.header(['平台', '主播', '开始时间', '结束时间', '最高在线', '二维码', '硬广'],
          project.options.color);
      let hide = project.options.hide;
      if (!hide.danmu)
        scheduleTable._header.push('弹幕数量');
      if (!hide.cost)
        scheduleTable._header.push('成本');
      if (!hide.click)
        scheduleTable._header.push('点击');
      if (!hide.added)
        scheduleTable._header.push('新增');
      if (!hide.reflux)
        scheduleTable._header.push('回流');
      scheduleTable.sumStartAt(4);
      scheduleTable.sumSkip([]);
      _.each(platformData, schedules => {
        let platform = schedules[0].platform.name;
        schedules.forEach((schedule, i) => {
          let qrcode = schedule.qrcode ? 1 : '';
          let yingguang = schedule.image ? 1 : '';
          let row = [
            platform,
            schedule.anchor.name,
            schedule.start,
            schedule.end,
            schedule.online,
            qrcode,
            yingguang];
          if (!hide.danmu)
            row.push(
                schedule.anchor.data[0] ? schedule.anchor.data[0].danmu : 0);
          if (!hide.cost)
            row.push(
                schedule.anchor.data[0] ? schedule.anchor.data[0].cost : 0);
          if (!hide.click)
            row.push(
                schedule.anchor.data[0] ? schedule.anchor.data[0].click : 0);
          if (!hide.added)
            row.push(
                schedule.anchor.data[0] ? schedule.anchor.data[0].added : 0);
          if (!hide.reflux)
            row.push(
                schedule.anchor.data[0] ? schedule.anchor.data[0].reflux : 0);
          scheduleTable.row(row);
        });
      });
    }

    /**硬广情况*/
    let yingGuang = '无';
    {
      let list = schedules.filter(schedule => schedule.image_id > 0);
      if (list.length > 0)
        yingGuang = '';
      list.forEach(schedule => {
        yingGuang += `<table style="margin:0 10px 10px 0;display:inline-block;border-collapse: collapse;${borderStyle};${tableWidth};${alignCenter};">
<tr style="background:${project.options.color};${borderStyle};color:#fff;">
<td>${schedule.platform.name} - ${schedule.anchor.name}</td>
</tr>
<tr>
<td>
<a href="https://live.beijingzhuyou.com/pic/${schedule.image.file}" target="_blank">
<img src="https://live.beijingzhuyou.com/pic/${schedule.image.file}_small">
</a>
</td>
</tr>
</table>`;
      });
    }
    const html = `<div style="padding: 10px 20px;font-size:16px;">
<div style="color: #999;font-size:12px">打开 <a href="https://live.beijingzhuyou.com/vpr/${report.index}" target="_blank">网址</a> 有更好的观看数据体验</div>
<h2 style="${alignCenter};">${project.name + ' ' + report.created_at} 数据日报</h2>
<h4>一，总体数据情况</h4>
${allPlatform}
${activeAnchorTable}
<br>
<h4>二，主播开播情况</h4>
${scheduleTable}
<h4>三，硬广情况</h4>
${yingGuang}
<h4>附加信息</h4>
<pre style="font-size:16px;">${appendContent}</pre>
</div>`;
    let now = moment(report.created_at).format('YYYY年MM月DD日');
    return {
      subject: `${project.name} ${now} 日志报告`,
      html,
      text: `请打开 https://live.beijingzhuyou.com/vpr/${report.index} 浏览`,
    };
  }
}

module.exports = SpiderReportData;